package com.dm.cloud.images.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.model.Container;
import com.dm.cloud.auth.common.po.AuthApp;
import com.dm.cloud.auth.feign.service.AuthAppService;
import com.dm.cloud.core.exception.CustomException;
import com.dm.cloud.core.mode.ResultModel;
import com.dm.cloud.images.common.po.ImagesContainer;
import com.dm.cloud.images.common.po.ImagesEndpoint;
import com.dm.cloud.images.mode.ContainerCreateMode;
import com.dm.cloud.images.mode.ContainerDetail;
import com.dm.cloud.images.service.ContainerService;
import com.dm.cloud.images.service.ImagesContainerService;
import com.dm.cloud.images.service.ImagesEndpointService;
import com.dm.cloud.images.service.ImagesShardService;
import com.dm.cloud.images.util.DockerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

/**
 * 容器管理服务类
 */
@Service
public class ContainerServiceImpl implements ContainerService {

    @Autowired
    private ImagesEndpointService imagesEndpointService;

    @Autowired
    private ImagesShardService imagesShardService;

    @Autowired
    private ImagesContainerService imagesContainerService;

    @Autowired
    private AuthAppService authAppService;

    @Override
    public List<ContainerDetail> list(String name,String nodeId) {
        List<ImagesEndpoint> endpoints=new ArrayList<>();
        if(StrUtil.isEmpty(nodeId)){
            endpoints = imagesEndpointService.list("state", 1);
        }else{
            ImagesEndpoint endpoint = imagesEndpointService.getById(nodeId);
            endpoints.add(endpoint);
        }
        List<ContainerDetail> containerDetails = new ArrayList<>();
        if (endpoints != null) {
            for (ImagesEndpoint endpoint : endpoints) {
                DockerClient client = null;
                try {
                    client = DockerUtil.get(endpoint.getHost(), endpoint.getDockerPort());
                    List<Container> containers = DockerUtil.listContainer(client, name);
                    List<ContainerDetail> containerDetailList = ContainerDetail.buildByContainerList(containers, endpoint.getId(), endpoint.getName(), endpoint.getHost());
                    containerDetails.addAll(containerDetailList);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        ResultModel<Map<String, String>> appCodeNameResult = authAppService.appCodeName();
        if(appCodeNameResult!=null && appCodeNameResult.getStatus()==200 && appCodeNameResult.getData()!=null){
            Map<String, String> appCodeName = appCodeNameResult.getData();
            //添加容器应用信息
            for (ContainerDetail containerDetail : containerDetails) {
                ImagesContainer containerModel=imagesContainerService.findImageContaniner(containerDetail.getNodeId(),containerDetail.getId());
                if(containerModel!=null){
                    containerDetail.setAppCode(containerModel.getAppCode());
                    containerDetail.setAppName(appCodeName.get(containerModel.getAppCode()));
                }
            }
        }

        return containerDetails;
    }

    private void buildAppDetail(ContainerDetail detail){
        ImagesContainer containerModel=imagesContainerService.findImageContaniner(detail.getNodeId(),detail.getId());
        if(containerModel!=null && StrUtil.isNotEmpty(containerModel.getAppCode())){
            detail.setAppCode(containerModel.getAppCode());
            ResultModel<AuthApp> app = authAppService.findByAppCode(containerModel.getAppCode());
            if(app!=null){
                detail.setAppName(app.getData().getName());
            }
        }
    }

    @Override
    public ContainerDetail create(ContainerCreateMode creatMode) {
        if (StrUtil.isEmpty(creatMode.getContainerName())) {
            throw new CustomException("容器名称不能为空!");
        }
        if (StrUtil.isEmpty(creatMode.getNodeId())) {
            throw new CustomException("请选择要部署的节点!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(creatMode.getNodeId());
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        //转义数据集挂载
        if(!creatMode.getVolumes().isEmpty()){
            Map<String, String> volumes = creatMode.getVolumes();
            Set<String> keys = volumes.keySet();
            Map<String, String> newVolumes=new HashMap<>();
            for (String key : keys) {
                String shardPath = key;
                String value=volumes.get(key);
                //判断是否为共享目录
                String shardRootPath=imagesShardService.ifShardReturnRootPath(shardPath,endPointPo.getDockerShard());
                if(shardRootPath!=null){
//                    volumes.remove(shardPath);
//                    volumes.put(shardRootPath,value);
                    // 添加shard_标识 ,证明是主机共享目录，如果是主机共享目录则后续挂载应使用Bings来挂载
//                    newVolumes.put(CommonProp.SHARD_VOLUME_PREFIX+shardRootPath,value);
                    newVolumes.put(shardRootPath,value);
                }else{
                    newVolumes.put(key,value);
                }
            }
            creatMode.setVolumes(newVolumes);
        }
        DockerClient dockerClient = null;
        try {
            dockerClient = DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Container container = DockerUtil.createContainer(dockerClient, creatMode);
            ContainerDetail detail = ContainerDetail.buildByContainer(container, endPointPo.getId(), endPointPo.getName(), endPointPo.getHost());
            //创建成功后关联应用
            if(creatMode.getAppCode()!=null){
                //添加容器信息
                imagesContainerService.insert(ImagesContainer
                        .builder()
                        .containerId(container.getId())
                        .nodeId(endPointPo.getId())
                        .appCode(creatMode.getAppCode())
                        .build());
            }
            return detail;
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }

    }

    @Override
    public ContainerDetail start(String nodeId, String id) {
        if (StrUtil.isEmpty(nodeId)) {
            throw new CustomException("节点ID不能为空!");
        }
        if (StrUtil.isEmpty(id)) {
            throw new CustomException("镜像ID不能为空!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(nodeId);
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        DockerClient dockerClient = null;
        try {
            dockerClient = DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Container container = DockerUtil.startContainer(dockerClient, id);
            ContainerDetail detail = ContainerDetail.buildByContainer(container, endPointPo.getId(), endPointPo.getName(), endPointPo.getHost());
            return detail;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException("启动失败!");
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }
    }

    @Override
    public ContainerDetail stop(String nodeId, String id) {
        if (StrUtil.isEmpty(nodeId)) {
            throw new CustomException("节点ID不能为空!");
        }
        if (StrUtil.isEmpty(id)) {
            throw new CustomException("镜像ID不能为空!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(nodeId);
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        DockerClient dockerClient = null;
        try {
            dockerClient = DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Container container = DockerUtil.stopContainer(dockerClient, id);
            ContainerDetail detail = ContainerDetail.buildByContainer(container, endPointPo.getId(), endPointPo.getName(), endPointPo.getHost());
            return detail;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException("关闭失败!");
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }
    }

    @Override
    public ContainerDetail restart(String nodeId, String id) {

        if (StrUtil.isEmpty(nodeId)) {
            throw new CustomException("节点ID不能为空!");
        }
        if (StrUtil.isEmpty(id)) {
            throw new CustomException("镜像ID不能为空!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(nodeId);
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        DockerClient dockerClient = null;
        try {
            dockerClient = DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Container container = DockerUtil.restartContainer(dockerClient, id);
            ContainerDetail detail = ContainerDetail.buildByContainer(container, endPointPo.getId(), endPointPo.getName(), endPointPo.getHost());
            return detail;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException("关闭失败!");
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }
    }

    @Override
    public Boolean delete(String nodeId, String id,Boolean delV) {
        if (StrUtil.isEmpty(nodeId)) {
            throw new CustomException("节点ID不能为空!");
        }
        if (StrUtil.isEmpty(id)) {
            throw new CustomException("镜像ID不能为空!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(nodeId);
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        DockerClient dockerClient = null;
        try {
            dockerClient=DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Boolean isOk = DockerUtil.deleteContainer(dockerClient, id, delV);
            if(isOk){
                imagesContainerService.deleteByNodeIdAndImagesId(id,nodeId);
            }
            return isOk;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            throw new CustomException("关闭失败!");
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }
    }

    @Override
    public ContainerDetail detail(String id, String nodeId) {
        if (StrUtil.isEmpty(nodeId)) {
            throw new CustomException("节点ID不能为空!");
        }
        if (StrUtil.isEmpty(id)) {
            throw new CustomException("镜像ID不能为空!");
        }
        ImagesEndpoint endPointPo = imagesEndpointService.getById(nodeId);
        if (endPointPo == null || ObjectUtil.isEmpty(endPointPo)) {
            throw new CustomException("节点不存在！");
        }
        DockerClient dockerClient = null;
        try {
            dockerClient = DockerUtil.get(endPointPo.getHost(), endPointPo.getDockerPort());
            Container container = DockerUtil.containerDetail(dockerClient, id);
            ContainerDetail detail = ContainerDetail.buildByContainer(container, endPointPo.getId(), endPointPo.getName(), endPointPo.getHost());
            buildAppDetail(detail);
            return detail;
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException("关闭失败!");
        } finally {
            try {
                dockerClient.close();
            } catch (Exception e) {

            }
        }
    }

    @Transactional
    @Override
    public ContainerDetail upApp(String id, String nodeId, String appCode) {
        ImagesContainer imageContaniner = imagesContainerService.findImageContaniner(nodeId, id);
        if(imageContaniner!=null){
            if(StrUtil.isEmpty(appCode)){
                imagesContainerService.clearContanierAppCode(nodeId, id);
            }else{
                imageContaniner.setAppCode(appCode);
                imagesContainerService.update(imageContaniner);
            }
        }else{
            imageContaniner=new ImagesContainer();
            imageContaniner.setContainerId(id);
            imageContaniner.setNodeId(nodeId);
            imageContaniner.setAppCode(appCode);
            imagesContainerService.insert(imageContaniner);
        }
        return detail(id,nodeId);
    }
}
